package raytracing

import "math"

type Sphere struct {
	Center   Vec3
	Radius   float64
	Material Material
}

func NewSphere(center Vec3, radius float64, material Material) *Sphere {
	return &Sphere{
		Center:   center,
		Radius:   radius,
		Material: material,
	}
}

func (s *Sphere) Hit(r *Ray, t_min float64, t_max float64, rec *HitRecord) bool {
	center := s.Center
	radius := s.Radius

	oc := r.Origin.Sub(center)
	a := r.Direction.LengthSquared()
	halfB := oc.Dot(r.Direction)
	c := oc.LengthSquared() - radius*radius
	discriminat := halfB*halfB - a*c
	if discriminat < 0 {
		return false
	}

	sqrtd := math.Sqrt(discriminat)
	root := (-halfB - sqrtd) / a
	if root < t_min || t_max < root {
		root = (-halfB + sqrtd) / a
		if root < t_min || t_max < root {
			return false
		}
	}

	rec.T = root
	rec.P = r.At(rec.T)
	rec.Material = s.Material
	outwardNormal := rec.P.Sub(center).DivScalar(radius)
	rec.SetFaceNormal(r, outwardNormal)
	return true
}
